#include "State.h"
#include <ctime>

State::State(void)
{
}

State::~State(void)
{
}

void State::setID(int pID)
{
    m_id = pID;
}

int State::getID()
{
    return m_id;
}

void State::execute(CHasUnit* pData, STATEPHASE pStatePhase)
{
    switch(pStatePhase)
    {
    case ENTER:
        onEnter(pData);
        break;
    case LEAVE:
        onLeave(pData);
        break;
    case MOVENEXT:
        moveNext(pData);
        break;
    }
}

CHasUnit::CHasUnit()
{
    m_currentUnit = NULL;
}

int CHasUnit::getStateID()
{
    return m_currentStateID;
}

void CHasUnit::setStateID(int pID)
{
    m_currentStateID = pID;
}

void CHasUnit::installState(int pID, int pTime)
{
    m_stateMgr->installState(pID, this, pTime);
}

void CHasUnit::setCurrentValied(bool pValied)
{
    if (NULL != m_currentUnit)
    {
        m_currentUnit->m_valid = pValied;
    }
}

void CHasUnit::setCurrentUnit(CUnit* pUnit)
{
    if (NULL != m_currentUnit)
    {
        m_currentUnit->m_valid = false;
    }

    m_currentUnit = pUnit;
    m_currentStateID = m_currentUnit->m_id;
}

void CHasUnit::setStateMgr(StateMgr* pMgr)
{
    m_stateMgr = pMgr;
}

void CHasUnit::moveNext()
{
    m_stateMgr->executeState(m_currentStateID, this, MOVENEXT);
}

StateMgr::StateMgr()
{
    memset(m_states, NULL, sizeof(m_states));
}

void StateMgr::addState(State* pState)
{
    m_states[pState->getID()] = pState;
}

void StateMgr::Run()
{
    while (true)
    {
        schedule();
        ThreadLib::YieldThread(1);
    }
}

void StateMgr::schedule()
{
    int now = clock() / (CLOCKS_PER_SEC * 1000);

    while( m_stateQueue.size() > 0 &&
           m_stateQueue.top()->m_time <= now )
    {
        CUnit* uint = m_stateQueue.top();
        m_stateQueue.pop();
        if (NULL != uint)
        {
            if (uint->m_valid)
            {
                executeState(uint->m_id, uint->m_data, LEAVE);
            }
            m_unitPoll.freePtrElement(uint);
        }
    }
}

void StateMgr::installState(int pId,CHasUnit* pData,int pTime)
{
    CUnit* uint = m_unitPoll.getPtrElement();
    if (NULL != uint)
    {
        uint->m_data = pData;
        uint->m_id = pId;
        uint->m_time = (clock() / (CLOCKS_PER_SEC * 1000)) + pTime;
        uint->m_valid = true;

        pData->setCurrentUnit(uint);

        executeState(pId, pData, ENTER);
        m_stateQueue.push(uint);
    }
}

void StateMgr::executeState(int pID, CHasUnit* pData, STATEPHASE pStatePhase)
{
    State*    state = m_states[pID];
    if (NULL != state)
    {
        state->execute(pData, pStatePhase);
    }
}
